package com.zhaoxi.project.sys.service.impl;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.zhaoxi.framework.web.BaseService;
import jakarta.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.zhaoxi.common.constant.UserConstants;
import com.zhaoxi.common.exception.ServiceException;
import com.zhaoxi.common.utils.DictUtils;
import com.zhaoxi.common.utils.StringUtils;
import com.zhaoxi.project.sys.domain.SysDictData;
import com.zhaoxi.project.sys.domain.SysDictType;
import com.zhaoxi.project.sys.mapper.SysDictDataMapper;
import com.zhaoxi.project.sys.mapper.SysDictTypeMapper;

/**
 * 字典 业务层处理
 *
 * @author zhaoxi
 */
@Service
public class SysDictTypeServiceImpl extends BaseService {
    @Autowired
    private SysDictTypeMapper dictTypeMapper;
    @Autowired
    private SysDictDataMapper dictDataMapper;

    /**
     * 0-1、数据预热：项目启动时初始化字典到缓存（xieleilei 12.6）
     */
    @PostConstruct
    public void init() {
        loadingDictCache();
    }

    /**
     * 0-2、数据预热——加载字典缓存数据（xieleilei 12.6）
     */

    public void loadingDictCache() {
        SysDictData dictData = new SysDictData();
        dictData.setStatus("0");
        Map<Long, Map<String, List<SysDictData>>> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(SysDictData::getTenantId, Collectors.groupingBy(SysDictData::getDictType)));
        // 外循环为了拿到租户id
        for (Map.Entry<Long, Map<String, List<SysDictData>>> entry1 : dictDataMap.entrySet()) {
            Long tenantId = entry1.getKey();
            Map<String, List<SysDictData>> sameTenantMap = entry1.getValue();
            //内循环就是同一租户下的字典缓存数组
            for (Map.Entry<String, List<SysDictData>> entry2 : sameTenantMap.entrySet()) {
                //键名需要拼接上租户id
                DictUtils.setDictCache(entry2.getKey() + "_" + tenantId, entry2.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList()));
            }
        }
    }

    /**
     * 1-1、字典类型管理——字典类型列表：通过租户id查询字典类型列表（xieleilei 12.6）
     *
     * @param dictType 字典类型信息
     * @return 字典类型集合信息
     */

    public List<SysDictType> selectDictTypeList(SysDictType dictType) {
        dictType.setTenantId(getTenantId());
        return dictTypeMapper.selectDictTypeList(dictType);
    }

    public List<SysDictType> selectSyncDictTypeList(SysDictType dictType) {
        //dictType.setDictId(1L);
        dictType.setParams("newTenantCreate", true);
        return dictTypeMapper.selectDictTypeList(dictType);
    }

    /**
     * 1-2、字典类型管理——修改字典类型时：根据字典类型ID查询信息（xieleilei 12.6）
     *
     * @param dictId 字典类型ID
     * @return 字典类型
     */

    public SysDictType selectDictTypeById(Long dictId) {
        SysDictType sysDictType = dictTypeMapper.selectDictTypeById(dictId);
        /*if(getUserId() != 1) {
            Long tenantId = sysDictType.getTenantId();
            if(tenantId == 1) {
                StringBuilder failureMsg = new StringBuilder();
                failureMsg.insert(0, "很抱歉，修改失败！ " + sysDictType.getDictName() + "为系统级字典，不允许修改");
                throw new ServiceException(failureMsg.toString());
            }
        }*/
        return sysDictType;
    }

    /*public List<SysDictData> selectDictTypeById(Long dictId) {
        SysDictData sysDictData = new SysDictData();
        SysDictType sysDictType = dictTypeMapper.selectDictTypeById(dictId);
        sysDictData.setDictType(sysDictType.getDictType());
        List<SysDictData> sysDictDataByType = selectDictDataByType(sysDictData);
        return sysDictDataByType;
    }*/

    /**
     * 1-3、字典类型管理——字典类型下拉框：条件搜索区域，通过租户id获取字典类型下拉框（xieleilei 12.6）
     *
     * @return 字典类型集合信息
     */

    public List<SysDictType> selectDictTypeAll(SysDictType dictType) {
        dictType.setTenantId(getTenantId());
        return dictTypeMapper.selectDictTypeAll(dictType);
    }

    /**
     * 1-4、根据字典类型查询信息：该方法未被使用 （xieleilei 12.6）
     *
     * @param dictType 字典类型
     * @return 字典类型
     */

    public SysDictType selectDictTypeByType(String dictType) {
        return dictTypeMapper.selectDictTypeByType(dictType);
    }

    /**
     * 1-5、字典类型管理——查看字典数据：根据字典类型查询对应的字典数据（xieleilei 12.6）
     * 先到缓存中查找，缓存没有再去数据库查找，然后将查到的热数据再塞到缓存当中
     *
     * @param dictData 字典类型
     * @return 字典数据集合信息
     */

    public List<SysDictData> selectDictDataByType(SysDictData dictData) {
        List<SysDictData> dictDatas = DictUtils.getDictCache(dictData.getDictType() + "_" + getTenantId());
        if (StringUtils.isNotEmpty(dictDatas)) {
            return dictDatas;
        }
        //一些自定义的系统表字典 2023年7月8日, PM 05:12:08
        //如果是经常变动的数据，直接返回，不缓存。反之则缓存
        if (dictData.getDictType().equals("sys_role_crm_sales")) {
            dictData.setParam1("sales");
            dictDatas = dictDataMapper.sys_role_roleKey(dictData);
        } else if (dictData.getDictType().equals("sys_role_wms_order")) {
            dictData.setParam1("order");
            dictDatas = dictDataMapper.sys_role_roleKey(dictData);
        } else if (dictData.getDictType().equals("hrp_partner")) {
            dictDatas = dictDataMapper.hrp_partner(dictData);
            return dictDatas;
        } else if (dictData.getDictType().equals("wms_product_line")) {
            dictDatas = dictDataMapper.wms_product_line(dictData);
        } else if (dictData.getDictType().equals("fms_account")) {
            dictDatas = dictDataMapper.fms_account(dictData);
        } else if (dictData.getDictType().equals("wms_product_code")) {
            dictDatas = dictDataMapper.wms_product_code(dictData);
        } else if (dictData.getDictType().equals("wms_product_stock")) {
            dictDatas = dictDataMapper.wms_product_stock(dictData);
            return dictDatas;
        } else if (dictData.getDictType().equals("wms_order_type")) {
            dictDatas = dictDataMapper.wms_order_type(dictData);
        } else if (dictData.getDictType().equals("wms_order_line_sum")) {
            dictDatas = dictDataMapper.wms_order_line_sum(dictData);
            return dictDatas;
        } else {
            dictDatas = dictDataMapper.selectDictDataByType(dictData);
        }
        if (StringUtils.isNotEmpty(dictDatas)) {
            //开发环境不用字典了，麻烦事。生产环境需要打开 2023年9月21日, PM 12:24:10
            DictUtils.setDictCache(dictData.getDictType() + "_" + getTenantId(), dictDatas);
            return dictDatas;
        }
        return null;
    }

    /**
     * 2-1、字典类型管理——新增字典类型：保证当前租户字典类型唯一，并且存入缓存（xieleilei 12.6）
     *
     * @param dict 字典类型信息
     * @return 结果
     */

    public int insertDictType(SysDictType dict) {
        dict.setTenantId(getTenantId());
        dict.setCreateBy(getUsername());
        int row = dictTypeMapper.insertDictType(dict);//存进数据库
        //字典类型存进缓存，键名后面拼接上 tenantId
        if (row > 0) DictUtils.setDictCache(dict.getDictType() + "_" + getTenantId(), null);
        return row;
    }

    /**
     * 2-2、字典类型管理——批量插入：新建租户时拷贝字典类型（xieleilei 12.6）
     *
     * @param dictTypes 字典类型
     * @return 结果
     */
    public int batchSysDictType(List<SysDictType> dictTypes) {
        return dictTypeMapper.batchSysDictType(dictTypes);
    }


    /**
     * 3-1、字典类型管理——修改字典类型（xieleilei 12.6）
     * 修改数据库字典类型的同时，同时要修改缓存
     *
     * @param newDictType 字典类型信息
     * @return 结果
     */

    @Transactional
    public int updateDictType(SysDictType newDictType) {
        newDictType.setUpdateBy(getUsername());
        //从数据库中得到旧的字典类型，将字典数据的旧类型更改为新类型
        SysDictType oldDictType = dictTypeMapper.selectDictTypeById(newDictType.getDictId());
        oldDictType.setTenantId(getTenantId());
        dictDataMapper.updateDictDataType(oldDictType, newDictType);
        //新建一个字典数据对象，字典类型是新的类型，目的是查询该字典类型的数据以放入缓存
        SysDictData dictData = new SysDictData();
        dictData.setDictType(newDictType.getDictType());
        //更新字典类型成功后，将对应的字典数据全部存入缓存，注意拼接租户id
        int row = dictTypeMapper.updateDictType(newDictType);
        if (row > 0) {
            List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictData);
            DictUtils.setDictCache(newDictType.getDictType() + "_" + getTenantId(), dictDatas);
        }
        return row;
    }


    /**
     * 4-1、字典类型管理——批量删除字典类型（xieleilei 12.6）
     * 查询字典类型对应字典数据的数量，以此判断字典类型是否可以删除，同时删除缓存
     *
     * @param dictIds 需要删除的字典ID
     */

    public void deleteDictTypeByIds(Long[] dictIds) {
        for (Long dictId : dictIds) {
            SysDictType dictType = selectDictTypeById(dictId);
            dictType.setTenantId(getTenantId());
            if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) {
                //%1$s表示第一个替换位置是以字符串类型放入，而%1$d是以整形放入，%2$s表示第二个替换位置是以字符串类型放入。
                throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
            }
            dictTypeMapper.deleteDictTypeById(dictId);
            DictUtils.removeDictCache(dictType.getDictType());
        }
    }

    /**
     * 4-2、字典类型管理——批量删除字典类型（xieleilei 12.6）
     * 删除租户时，不无需验证直接删除字典类型
     *
     * @param tenantId 租户id
     */
    public int deleteDictTypeByTenantId(Long tenantId) {
        return dictTypeMapper.deleteDictTypeByTenantId(tenantId);
    }

    /**
     * 5-1、清空字典缓存数据（xieleilei 12.6）
     * 与字典相关的，以 sys_dict开头的缓存数据都会被清除
     */

    public void clearDictCache() {
        DictUtils.clearDictCache();
    }

    /**
     * 5-2、重置字典缓存数据（xieleilei 12.6）
     * 重置与预热一样，调用加载缓存的方法
     */

    public void resetDictCache() {
        clearDictCache();
        loadingDictCache();
    }


    /**
     * 6-1、新增字典类型时关键字校检：校验当前租户的字典关键字是否唯一（xieleilei 12.6）
     *
     * @param dict 字典类型
     * @return 结果
     */

    public boolean checkDictTypeUnique(SysDictType dict) {
        dict.setTenantId(getTenantId());//新增时需要设置租户id
        Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId();
        //根据一个字典类型找到不同的字典id，说明重复，返回 NOT_UNIQUE
        SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType());
        if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue()) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

}

